package com.atguigu.spzx.cart.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.cart.service.CartService;
import com.atguigu.spzx.feign.product.ProductFeignClient;
import com.atguigu.spzx.model.entity.h5.CartInfo;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.service.utils.AuthContextUtils;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ClassName: CartServiceImpl
 * Package: com.atguigu.spzx.cart.service.impl
 * Description:
 *
 * @Author 刘强
 * @Create 2024/7/17 9:58
 * @Version 1.0
 */
@Service
public class CartServiceImpl implements CartService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ProductFeignClient productFeignClient;

    /**
     * 添加到购物车
     * @param skuId
     * @param count
     */
    @Override
    public void addToCart(Long skuId, Integer count) {
        // 1. 先查询redis中是否已经有该用户的该购物车项了
                //获取用户id
        Long userId = AuthContextUtils.get().getId();
        String cartInfoJson = (String) stringRedisTemplate.opsForHash().get(getCartKey(userId), getCartItemKey(skuId));
        CartInfo cartInfo = null;
        if(!StrUtil.isEmpty(cartInfoJson)){
            // 不为空，表明redis中已经存储了该用户对应的该购物车项了，所以我们只需要修改数量即可
             cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
            cartInfo.setSkuNum(cartInfo.getSkuNum() + count);
            cartInfo.setUpdateTime(new Date());
        }else {
            // 为空，则表明redis中还没有该用户的该购物车项信息，所以我们要通过openFeign远程访问商品服务，
            // 从而获取商品sku信息来封装到当前的购物车项信息中，然后更新购物车项数量再保存到redis中
            ProductSku productSku = productFeignClient.getBySkuId(skuId);
             cartInfo = buildCartInfo(skuId, count, productSku, userId);
        }

        stringRedisTemplate.opsForHash().put(getCartKey(userId),getCartItemKey(skuId),JSON.toJSONString(cartInfo));

    }

    /**
     * 查询购物车列表
     * @return
     */
    @Override
    public List<CartInfo> cartList() {
        Long userId = AuthContextUtils.get().getId();
        List<CartInfo> cartInfoList = stringRedisTemplate.opsForHash().values(getCartKey(userId))
                .stream().map(cartInfoObj -> {
                    return JSON.parseObject(cartInfoObj.toString(), CartInfo.class);
                }).sorted((CartInfo o1, CartInfo o2)->  o2.getCreateTime().compareTo(o1.getCreateTime())
                ).collect(Collectors.toList());
        return cartInfoList;
    }

    /**
     * 删除购物车项
     * @param skuId
     */
    @Override
    public void deleteCart(Long skuId) {
        Long userId = AuthContextUtils.get().getId();
        String cartKey = getCartKey(userId);
        String cartItemKey = getCartItemKey(skuId);
        stringRedisTemplate.opsForHash().delete(cartKey,cartItemKey);
    }

    /**
     * 跟新购物车项的选中状态
     * @param skuId
     * @param isChecked
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = AuthContextUtils.get().getId();
        String cartKey = getCartKey(userId);
        String cartItemKey = getCartItemKey(skuId);
        String cartItemJson = stringRedisTemplate.opsForHash().get(cartKey, cartItemKey).toString();
        CartInfo cartInfo = JSON.parseObject(cartItemJson, CartInfo.class);
        cartInfo.setIsChecked(isChecked);
        stringRedisTemplate.opsForHash().put(cartKey,cartItemKey,JSON.toJSONString(cartInfo));

    }

    /**
     * 全选状态的修改
     * @param isChecked
     */
    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = AuthContextUtils.get().getId();
        String cartKey = getCartKey(userId);
        List<Object> cartItemObjList = stringRedisTemplate.opsForHash().values(cartKey);
        if(!CollectionUtils.isEmpty(cartItemObjList)){
            cartItemObjList.stream().forEach(cartItemObj->{
                CartInfo cartInfo = JSON.parseObject(cartItemObj.toString(), CartInfo.class);
                cartInfo.setIsChecked(isChecked);
                stringRedisTemplate.opsForHash().put(cartKey,getCartItemKey(cartInfo.getSkuId()),JSON.toJSONString(cartInfo));
            });
        }
    }

    /**
     * 清空购物车
     */
    @Override
    public void clearCart() {
        Long userId = AuthContextUtils.get().getId();
        String cartKey = getCartKey(userId);
        stringRedisTemplate.delete(cartKey);
    }

    /**
     * 根据token获取所有选中的购物车项
     * @return
     */
    @Override
    public List<CartInfo> getAllCkecked() {
        Long userId = AuthContextUtils.get().getId();
        List<Object> cartItemObjList = stringRedisTemplate.opsForHash().values(getCartKey(userId));
        List<CartInfo> cartInfoList = cartItemObjList.stream()
                .map(cartItemObj -> JSON.parseObject(cartItemObj.toString(), CartInfo.class))
                .filter(cartInfo -> cartInfo.getIsChecked() == 1)
                .collect(Collectors.toList());
        return cartInfoList;
    }

    /**
     * 清空选中的购物车项
     */
    @Override
    public void clearChecked() {
        Long userId = AuthContextUtils.get().getId();
        List<Object> cartItemObjList = stringRedisTemplate.opsForHash().values(getCartKey(userId));
        if(CollectionUtils.isEmpty(cartItemObjList)){
            return;
        }
        cartItemObjList.stream().map(cartItemObj->{
            CartInfo cartInfo = JSON.parseObject(cartItemObj.toString(), CartInfo.class);
            return cartInfo;
        }).forEach(cartInfo -> {
            if(cartInfo.getIsChecked()==1){
                stringRedisTemplate.opsForHash().delete(getCartKey(userId),getCartItemKey(cartInfo.getSkuId()));
            }
        });
    }

    private static CartInfo buildCartInfo(Long skuId, Integer count, ProductSku productSku, Long userId) {
        CartInfo cartInfo = new CartInfo();
        cartInfo.setCartPrice(productSku.getSalePrice());
        cartInfo.setCurrentPrice(productSku.getSalePrice());
        cartInfo.setImgUrl(productSku.getThumbImg());
        cartInfo.setIsChecked(1);
        cartInfo.setSkuId(skuId);
        cartInfo.setSkuName(productSku.getSkuName());
        cartInfo.setSkuNum(count);
        cartInfo.setUserId(userId);
        cartInfo.setCreateTime(new Date());
        cartInfo.setUpdateTime(new Date());
        return cartInfo;
    }

    @NotNull
    private static String getCartItemKey(Long skuId) {
        return "cartItem:" + skuId;
    }

    private static String getCartKey(Long userId) {
        return "cart:" + userId;
    }
}
